<?php

/**
 * This is the model class for table "tbl_api_token".
 *
 * The followings are the available columns in table 'tbl_api_token':
 * @property integer $id
 * @property integer $user_id
 * @property integer $uptime
 * @property string $token
 * @property string $ip
 * @property-read User $user
 * @property-read ApiLog[] $logs
 * @property-read boolean $isValid whether the token is valid
 */
class ApiToken extends CActiveRecord
{
	const EXPIRES_IN = 86400;

	/**
	 * @return string the associated database table name
	 */
	public function tableName()
	{
		return 'tbl_api_token';
	}

	/**
	 * @return array relational rules.
	 */
	public function relations()
	{
		return array(
			'user' => array(self::BELONGS_TO, 'User', 'user_id'),
			'logs' => array(self::HAS_MANY, 'ApiLog', 'token_id'),
		);
	}

	/**
	 * @return array customized attribute labels (name=>label)
	 */
	public function attributeLabels()
	{
		return array(
			'id' => 'ID',
			'user_id' => '用户名',
			'uptime' => '登入时间',
			'token' => 'Token',
			'ip' => 'IP 地址',
		);
	}

	/**
	 * Whether the model is valid (not expires AND correct ip address)
	 * @return boolean
	 */
	public function getIsValid()
	{
		return $this->ip === $_SERVER['REMOTE_ADDR'] && $this->uptime > (time() - self::EXPIRES_IN);
	}

	/**
	 * Find valid model by token
	 * @param string $token
	 * @return ApiToken
	 */
	public function findByToken($token)
	{
		$model = self::model()->with('user')->findByAttributes(array('token' => $token));
		if ($model === null || !$model->getIsValid()) {
			return null;
		}
		return $model;
	}

	/**
	 * Add a log record
	 * @param string $content
	 */
	public function addLog($content)
	{
		$model = new ApiLog;
		$model->token_id = $this->id;
		$model->content = $content;
		return $model->save(false);
	}

	/**
	 * Logout the token
	 */
	public function logout()
	{
		return $this->delete();
	}

	/**
	 * Override to set some attributes before save
	 * @return boolean
	 */
	protected function beforeSave()
	{
		if ($this->isNewRecord) {
			$this->ip = $_SERVER['REMOTE_ADDR'];
			do {
				$this->token = md5(microtime() . $this->ip);
			} while (self::model()->findByAttributes(array('token' => $this->token)) !== null);
		}
		$this->uptime = time();
		return parent::beforeSave();
	}

	/**
	 * Returns the static model of the specified AR class.
	 * Please note that you should have this exact method in all your CActiveRecord descendants!
	 * @param string $className active record class name.
	 * @return ApiToken the static model class
	 */
	public static function model($className = __CLASS__)
	{
		return parent::model($className);
	}
}
